The Stripe Subscription API is a simple way to integrate recurring website payments For recurring billing, subscription payment is required if you want to implement the membership subscription system on the web application. The Stripe payment gateway allows you to integrate recurring payment with the APIs. Stripe subscription is a fast and efficient way for you to buy membership online with a credit card.
In the Stripe subscription payment, the buyer is recurringly charged on the basis of a specific period of time. Your website members will agree to a plan and make the payment without leaving the website with their credit/debit card. We will show you how to integrate Stripe subscription payment with PHP in this tutorial.
Take a look at the directory layout before you begin implementing Stripe Subscription Payment API in PHP.
2 3 4 5 6 7 8 |
stripe_subscription_payment_php/ ├── dbconfig.php ├── index.php ├── payment.php ├── stripe-php/ |
Generate Stripe Test API Keys
You need the test API keys data to check the subscription payment process.
- Login to your Stripe account and navigate to the Developers » API keys page.
- In the TEST DATA block, you’ll see the API keys (Publishable key and Secret key) are listed under the Standard keys section. To show the Secret key, click on the Reveal test key token button.
Copay and Paste the Publishable key and Secret key in your Notepad to use later in the script.
Download Stripe PHP Library
The Stripe PHP library is used to access the PHP Stripe API. It helps create customer, plan, and subscription to Stipre API. The required library files should be included in our source code.
Create Plans, Stripe API and Database Configuration (dbconfig.php)
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<?php // Subscription plans $plans = array( '1' => array( 'name' => 'Weekly Subscription', 'price' => 25, 'interval' => 'week' ), '2' => array( 'name' => 'Monthly Subscription', 'price' => 80, 'interval' => 'month' ), '3' => array( 'name' => 'Yearly Subscription', 'price' => 850, 'interval' => 'year' ) ); //Currency code $currency = "usd"; // Stripe API configuration define('STRIPE_API_KEY', 'Your_API_Secret_key'); //STRIPE_API_KEY – Specify the API Secret key. define('STRIPE_PUBLISHABLE_KEY', 'Your_API_Publishable_key'); //STRIPE_PUBLISHABLE_KEY – Specify the API Publishable key. // Database configuration define('DB_HOST', 'MySQL_Database_Host'); define('DB_USERNAME', 'MySQL_Database_Username'); define('DB_PASSWORD', 'MySQL_Database_Password'); define('DB_NAME', 'MySQL_Database_Name'); // Connect with the database $db = new mysqli(DB_HOST, DB_USERNAME, DB_PASSWORD, DB_NAME); // Display error if failed to connect if ($db->connect_errno) { printf("Connect failed: %s\n", $db->connect_error); exit(); } |
Note: Stripe API Secret key and Publishable key will be found in the API Keys Data section of your Stripe account.
Create Database Tables
Two tables are required in the database to store the member and subscription information.
1. The following SQL creates an users
table to hold the member’s info in the MySQL database.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
CREATE TABLE `users` ( `id` int(11) NOT NULL AUTO_INCREMENT, `subscription_id` int(11) NOT NULL DEFAULT '0', `first_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL, `last_name` varchar(25) COLLATE utf8_unicode_ci NOT NULL, `email` varchar(50) COLLATE utf8_unicode_ci NOT NULL, `password` varchar(255) COLLATE utf8_unicode_ci NOT NULL, `gender` enum('Male','Female') COLLATE utf8_unicode_ci NOT NULL, `phone` varchar(15) COLLATE utf8_unicode_ci NOT NULL, `created` datetime NOT NULL, `modified` datetime NOT NULL, `status` enum('1','0') COLLATE utf8_unicode_ci NOT NULL DEFAULT '1', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; |
2. The following SQL creates a user_subscriptions_details
table to hold the subscription info in the MySQL database.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
CREATE TABLE `user_subscriptions_details` ( `id` int(11) NOT NULL AUTO_INCREMENT, `user_id` int(11) NOT NULL DEFAULT '0', `payment_method` enum('stripe') COLLATE utf8_unicode_ci NOT NULL DEFAULT 'stripe', `stripe_subscription_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL, `stripe_customer_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL, `stripe_plan_id` varchar(50) COLLATE utf8_unicode_ci NOT NULL, `plan_amount` float(10,2) NOT NULL, `plan_amount_currency` varchar(10) COLLATE utf8_unicode_ci NOT NULL, `plan_interval` varchar(10) COLLATE utf8_unicode_ci NOT NULL, `plan_interval_count` tinyint(2) NOT NULL, `payer_email` varchar(50) COLLATE utf8_unicode_ci NOT NULL, `created` datetime NOT NULL, `plan_period_start` datetime NOT NULL, `plan_period_end` datetime NOT NULL, `status` varchar(50) COLLATE utf8_unicode_ci NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; |
Create Stripe Subscription Form (index.php)
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
<?php // Include configuration file require_once 'dbconfig.php'; ?> <script src="https://js.stripe.com/v2/"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script> <div class="panel"> <form action="payment.php" method="POST" id="paymentFrm"> <div class="panel-heading"> <h3 class="panel-title">Plan Subscription with Stripe</h3> <!-- Plan Info --> <p> <b>Select Plan:</b> <select name="subscr_plan" id="subscr_plan"> <?php foreach($plans as $id=>$plan){ ?> <option value="<?php echo $id; ?>"><?php echo $plan['name'].' [$'.$plan['price'].'/'.$plan['interval'].']'; ?></option> <?php } ?> </select> </p> </div> <div class="panel-body"> <!-- Display errors returned by createToken --> <div class="card-errors"></div> <!-- Payment form --> <div class="form-group"> <label>NAME</label> <input type="text" name="name" id="name" placeholder="Enter name" required="" autofocus=""> </div> <div class="form-group"> <label>EMAIL</label> <input type="email" name="email" id="email" placeholder="Enter email" required=""> </div> <div class="form-group"> <label>CARD NUMBER</label> <input type="text" name="card_number" id="card_number" placeholder="1234 1234 1234 1234" maxlength="16" autocomplete="off" required=""> </div> <div class="row"> <div class="left"> <div class="form-group"> <label>EXPIRY DATE</label> <div class="col-1"> <input type="text" name="card_exp_month" id="card_exp_month" placeholder="MM" maxlength="2" required=""> </div> <div class="col-2"> <input type="text" name="card_exp_year" id="card_exp_year" placeholder="YYYY" maxlength="4" required=""> </div> </div> </div> <div class="right"> <div class="form-group"> <label>CVC CODE</label> <input type="text" name="card_cvc" id="card_cvc" placeholder="CVC" maxlength="3" autocomplete="off" required=""> </div> </div> </div> <button type="submit" class="btn btn-success" id="payBtn">Submit Payment</button> </div> </form> </div> <script> // Set your publishable key Stripe.setPublishableKey('<?php echo STRIPE_PUBLISHABLE_KEY; ?>'); // Callback to handle the response from stripe function stripeResponseHandler(status, response) { if (response.error) { // Enable the submit button $('#payBtn').removeAttr("disabled"); // Display the errors on the form $(".payment-status").html('<p>'+response.error.message+'</p>'); } else { var form$ = $("#paymentFrm"); // Get token id var token = response.id; // Insert the token into the form form$.append("<input type='hidden' name='stripeToken' value='" + token + "' />"); // Submit form to the server form$.get(0).submit(); } } $(document).ready(function() { // On form submit $("#paymentFrm").submit(function() { // Disable the submit button to prevent repeated clicks $('#payBtn').attr("disabled", "disabled"); // Create single-use token to charge the user Stripe.createToken({ number: $('#card_number').val(), exp_month: $('#card_exp_month').val(), exp_year: $('#card_exp_year').val(), cvc: $('#card_cvc').val() }, stripeResponseHandler); // Submit from callback return false; }); }); </script> |
In the above code:
2 3 4 5 |
//Create Stripe Token and Validate Card with Stripe.js Library: <script src="https://js.stripe.com/v2/"></script> |
the Stripe.js library that helps securely sending sensitive information (credit card) to Stripe directly from the browser.
The following JavaScript code is used to generate a token with the Stripe.js library.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
<script> // Set your publishable key Stripe.setPublishableKey('<?php echo STRIPE_PUBLISHABLE_KEY; ?>'); // Callback to handle the response from stripe function stripeResponseHandler(status, response) { if (response.error) { // Enable the submit button $('#payBtn').removeAttr("disabled"); // Display the errors on the form $(".payment-status").html('<p>'+response.error.message+'</p>'); } else { var form$ = $("#paymentFrm"); // Get token id var token = response.id; // Insert the token into the form form$.append("<input type='hidden' name='stripeToken' value='" + token + "' />"); // Submit form to the server form$.get(0).submit(); } } $(document).ready(function() { // On form submit $("#paymentFrm").submit(function() { // Disable the submit button to prevent repeated clicks $('#payBtn').attr("disabled", "disabled"); // Create single-use token to charge the user Stripe.createToken({ number: $('#card_number').val(), exp_month: $('#card_exp_month').val(), exp_year: $('#card_exp_year').val(), cvc: $('#card_cvc').val() }, stripeResponseHandler); // Submit from callback return false; }); }); </script> |
Process Subscription Payment (payment.php)
In this file, the submitted card details are validated and the subscription plan is activated with Stripe API using PHP.
- Get the logged-in user ID from the SESSION.
- Retrieve the token, selected plan, card details, and buyer info from the form fields using the PHP $_POST method.
- Fetch the plan details (name, price, and term) from the $plans array.
- Include the Stripe PHP library.
- Set API Secret key using setApiKey() method of Stripe class.
- Add the customer using
create()
method of Stripe Customer API.- email – Buyer email
- source – Stripe token
- Create a plan using the
create()
method of Stripe Plan API.- product – The product whose pricing the created plan will represent.
- product.name – Plan name.
- amount – A positive integer in cents (or 0 for a free plan) which will charge on a recurring basis.
- currency – Three-letter ISO currency code in lowercase.
- interval – Specify billing frequency (day, week, month or year).
- interval_count – The number of intervals between subscription billings. For example, interval=month and interval_count=2 bills every 2 months. Maximum of one year (1 year, 12 months, or 52 weeks) interval allowed.
- product – The product whose pricing the created plan will represent.
- Create a subscription using
create()
method of Stripe Subscription API.- customer – The identifier of the customer to subscribe.
- items – List of the subscription plans.
- items.plan – Attach plan ID.
- If the plan and subscription creation are successful, retrieve transaction data. On successful activation,
- Insert the subscription information into the database.
- Attach the subscription reference ID to the respective member.
- Display subscription payment status on the webpage.
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
<?php // Include configuration file require_once 'dbconfig.php'; // Get user ID from current SESSION $userID = isset($_SESSION['loggedInUserID'])?$_SESSION['loggedInUserID']:1; $payment_id = $statusMsg = $api_error = ''; $ordStatus = 'error'; // Check whether stripe token is not empty if(!empty($_POST['subscr_plan']) && !empty($_POST['stripeToken'])){ // Retrieve stripe token, card and user info from the submitted form data $token = $_POST['stripeToken']; $name = $_POST['name']; $email = $_POST['email']; $card_number = preg_replace('/\s+/', '', $_POST['card_number']); $card_exp_month = $_POST['card_exp_month']; $card_exp_year = $_POST['card_exp_year']; $card_cvc = $_POST['card_cvc']; // Plan info $planID = $_POST['subscr_plan']; $planInfo = $plans[$planID]; $planName = $planInfo['name']; $planPrice = $planInfo['price']; $planInterval = $planInfo['interval']; // Include Stripe PHP library require_once 'stripe-php/init.php'; // Set API key \Stripe\Stripe::setApiKey(STRIPE_API_KEY); // Add customer to stripe $customer = \Stripe\Customer::create(array( 'email' => $email, 'source' => $token )); // Convert price to cents $priceCents = round($planPrice*100); // Create a plan try { $plan = \Stripe\Plan::create(array( "product" => [ "name" => $planName ], "amount" => $priceCents, "currency" => $currency, "interval" => $planInterval, "interval_count" => 1 )); }catch(Exception $e) { $api_error = $e->getMessage(); } if(empty($api_error) && $plan){ // Creates a new subscription try { $subscription = \Stripe\Subscription::create(array( "customer" => $customer->id, "items" => array( array( "plan" => $plan->id, ), ), )); }catch(Exception $e) { $api_error = $e->getMessage(); } if(empty($api_error) && $subscription){ // Retrieve subscription data $subsData = $subscription->jsonSerialize(); // Check whether the subscription activation is successful if($subsData['status'] == 'active'){ // Subscription info $subscrID = $subsData['id']; $custID = $subsData['customer']; $planID = $subsData['plan']['id']; $planAmount = ($subsData['plan']['amount']/100); $planCurrency = $subsData['plan']['currency']; $planinterval = $subsData['plan']['interval']; $planIntervalCount = $subsData['plan']['interval_count']; $created = date("Y-m-d H:i:s", $subsData['created']); $current_period_start = date("Y-m-d H:i:s", $subsData['current_period_start']); $current_period_end = date("Y-m-d H:i:s", $subsData['current_period_end']); $status = $subsData['status']; // Insert transaction data into the database $sql = "INSERT INTO user_subscriptions_details (user_id,stripe_subscription_id,stripe_customer_id,stripe_plan_id,plan_amount,plan_amount_currency,plan_interval,plan_interval_count,payer_email,created,plan_period_start,plan_period_end,status) VALUES('".$userID."','".$subscrID."','".$custID."','".$planID."','".$planAmount."','".$planCurrency."','".$planinterval."','".$planIntervalCount."','".$email."','".$created."','".$current_period_start."','".$current_period_end."','".$status."')"; $insert = $db->query($sql); // Update subscription id in the users table if($insert && !empty($userID)){ $subscription_id = $db->insert_id; $update = $db->query("UPDATE users SET subscription_id = {$subscription_id} WHERE id = {$userID}"); } $ordStatus = 'success'; $statusMsg = 'Your Subscription Payment has been Successful!'; }else{ $statusMsg = "Subscription activation failed!"; } }else{ $statusMsg = "Subscription creation failed! ".$api_error; } }else{ $statusMsg = "Plan creation failed! ".$api_error; } }else{ $statusMsg = "Error on form submission, please try again."; } ?> <div class="container"> <div class="status"> <h1 class="<?php echo $ordStatus; ?>"><?php echo $statusMsg; ?></h1> <?php if(!empty($subscrID)){ ?> <h4>Payment Information</h4> <p><b>Reference Number:</b> <?php echo $subscription_id; ?></p> <p><b>Transaction ID:</b> <?php echo $subscrID; ?></p> <p><b>Amount:</b> <?php echo $planAmount.' '.$planCurrency; ?></p> <h4>Subscription Information</h4> <p><b>Plan Name:</b> <?php echo $planName; ?></p> <p><b>Amount:</b> <?php echo $planPrice.' '.$currency; ?></p> <p><b>Plan Interval:</b> <?php echo $planInterval; ?></p> <p><b>Period Start:</b> <?php echo $current_period_start; ?></p> <p><b>Period End:</b> <?php echo $current_period_end; ?></p> <p><b>Status:</b> <?php echo $status; ?></p> <?php } ?> </div> <a href="index.php" class="btn-link">Back to Subscription Page</a> </div> |
Test Card Details
- 4242424242424242 – Visa
- 4000056655665556 – Visa (debit)
- 5555555555554444 – Mastercard
- 5200828282828210 – Mastercard (debit)
- 378282246310005 – American Express
- 6011111111111117 – Discover
Expiration date : 10/2021
CVC number : 123 (Any random number)
Make Stripe Payment Gateway Live
Follow the steps below to make Stripe payment gateway live once the subscription API integration is complete and the payment process works properly.
- Login to your Stripe account and navigate to the Developers » API keys page.
- Collect the API keys (Publishable key and Secret key) from the LIVE DATA section.
- In the
dbconfig.php
file, replace the Test API keys (Publishable key and Secret key) by the Live API keys (Publishable key and Secret key).
SEE ALSO: How to Integrate Paypal Payment System with Paypal API in PHP and MySql
Conclusion
Stripe subscription payment API is the simplest way to accept online subscription credit payment. Using Stripe API and PHP, you can implement the recurring billing featured in the web application. Our example script allows you to periodically charge the user via Stripe at a specific interval. This Stripe payment script’s functionality can be enhanced as per your needs.
Are you want to get implementation help, or modify or extend the functionality of this script? Submit paid service request
Pradeep Maurya is the Professional Web Developer & Designer and the Founder of “Tutorials website”. He lives in Delhi and loves to be a self-dependent person. As an owner, he is trying his best to improve this platform day by day. His passion, dedication and quick decision making ability to stand apart from others. He’s an avid blogger and writes on the publications like Dzone, e27.co